package com.csg.ses.ws.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.csg.ses.common.utils.CommonUtil;
import com.csg.ses.dao.ses.YxzjkKhYhzhDao;
import com.csg.ses.dao.ses.YxzjkLcCbxxDao;
import com.csg.ses.dao.ses.YxzjkZwCsxxDao;
import com.csg.ses.dao.yxxt.YxxtYxzjkKhYhzhDao;
import com.csg.ses.dao.yxxt.YxxtYxzjkLcCbxxDao;
import com.csg.ses.dao.yxxt.YxxtYxzjkZwCsxxDao;
import com.csg.ses.entity.ses.YxzjkKhYhzhEntity;
import com.csg.ses.entity.ses.YxzjkLcCbxxEntity;
import com.csg.ses.entity.ses.YxzjkZwCsxxEntity;
import com.csg.ses.entity.yxxt.YxxtYxzjkKhYhzhEntity;
import com.csg.ses.entity.yxxt.YxxtYxzjkLcCbxxEntity;
import com.csg.ses.entity.yxxt.YxxtYxzjkZwCsxxEntity;
import com.csg.ses.feign.VcsService;
import com.csg.ses.ws.ZncfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.jws.WebService;
import java.util.*;

/**
 * @auther wangjun
 * @time 2020/11/19 12:04
 * 智能催费服务实现类
 */
@Component
@WebService(serviceName = "ZncfService",
        targetNamespace = "http://ws.ses.csg.com/",
        endpointInterface = "com.csg.ses.ws.ZncfService")
public class ZncfServiceImpl implements ZncfService {

    @Autowired
    private YxxtYxzjkZwCsxxDao yxxtCsxxDao;

    @Autowired
    private YxzjkZwCsxxDao sesCsxxDao;

    @Autowired
    private YxxtYxzjkKhYhzhDao yxyhzhDao;

    @Autowired
    private YxzjkKhYhzhDao sesYhzhDao;

    @Autowired
    private YxxtYxzjkLcCbxxDao yxcbxxDao;

    @Autowired
    private YxzjkLcCbxxDao sesCbxxDao;

    @Autowired
    private VcsService vcsService;

    /**
     * 发送催费用户清单通知
     * @param dqbm
     * @param yxpch
     * @param pcjls
     * @return
     */
    @Override
    public String fscfyhqdtz(String dqbm, String yxpch, String pcjls) {
        LinkedHashMap<String, String> result = new LinkedHashMap<>();
        String replyCode = "OK";
        String replyMsg = "";

        try {
            if (dqbm != null && yxpch != null && pcjls != null) {
                replyMsg = "智能机器人已收到营销系统通知，将从营销中间库同步" + yxpch + "批次的" + pcjls + "条用户数据！";
                //判断营销传过来的批次记录数与中间库数量是否一致
                Integer jls = yxxtCsxxDao.getPcjls(dqbm, yxpch);
                if (Integer.valueOf(pcjls) != jls) {
                    replyCode = "ERROR";
                    replyMsg = "被通知的批次" + yxpch + "记录数" + pcjls + "与营销中间库记录数" + jls + "不一致！";
                } else {
                    //创建线程，从营销中间库取数
                    Thread thread = new Thread(() -> {
                        this.generateTask(dqbm, yxpch);   //生成机器人任务
                    });
                    thread.start();
                }
            } else {
                replyCode = "ERROR";
                replyMsg = "地区编码、营销批次号、批次记录数不能为空！";
            }
        } catch (Exception e) {
            e.printStackTrace();
            replyCode = "ERROR";
            replyMsg = "接收通知失败！";
        } finally {
            result.put("replyCode", replyCode);
            result.put("replyMsg", replyMsg);
            return JSON.toJSONString(result);
        }
    }

    /**
     * 生成机器人任务
     * @param dqbm
     * @param yxpch
     */
    public void generateTask(String dqbm, String yxpch) {
        try {
            // 1.获取营销系统数据，写入本地库
            this.getYxxtData(dqbm, yxpch);

            // 2.调用函数进行手机号码去重处理
            this.p_handle_phone_numbers(yxpch);

            // 3.从本地数据库获取已经进行去重之后的用户信息
            List<YxzjkZwCsxxEntity> sesCsxxList = this.getIsValidCsxx(dqbm, yxpch);

            // 4.添加外呼号码
            String task_id = vcsService.pustPhones(dqbm, yxpch, sesCsxxList);

            // 5.更新同一营销批次的任务号
            this.updateTaskIdByYxpch(yxpch, task_id);

            // 6.休眠2分钟，等待任务详情的状态从"准备中"变成"未呼叫"
            new Thread().sleep(1000  * 60 * 2); //休眠2分钟

            // 7.启动任务，自动外呼进行电费催缴（如果启动失败，则接下来每隔1分钟重启一次，最多重启3次）
            Boolean flag = vcsService.resumeOrPause(task_id, true);
            if (!flag) {
                for (int i = 0; i < 3; i ++) {
                    new Thread().sleep(1000  * 60 * 1); //休眠1分钟
                    flag = vcsService.resumeOrPause(task_id, true);
                    if (flag) return;
                }
            }
        } catch (Exception e) {
            e.getMessage();
        }
    }

    /**
     * 获取营销系统数据，写入本地库
     * @param dqbm
     * @param yxpch
     */
    @Transactional
    public void getYxxtData(String dqbm, String yxpch) {
        // 1.获取营销中间库催收信息数据
        QueryWrapper<YxxtYxzjkZwCsxxEntity> qw = new QueryWrapper();
        qw.eq("DQBM", dqbm);
        qw.eq("YXPCH", yxpch);
        List<YxxtYxzjkZwCsxxEntity> yxcsxxList = yxxtCsxxDao.selectList(qw);

        // 2.获取营销中间库银行账号信息
        QueryWrapper<YxxtYxzjkKhYhzhEntity> qw2 = new QueryWrapper<>();
        qw2.eq("YXPCH", yxpch);
        List<YxxtYxzjkKhYhzhEntity> yxyhzhList = yxyhzhDao.selectList(qw2);

        // 3.获取营销中间库抄表信息
        QueryWrapper<YxxtYxzjkLcCbxxEntity> qw3 = new QueryWrapper<>();
        qw3.eq("YXPCH", yxpch);
        List<YxxtYxzjkLcCbxxEntity> yxcbxxList = yxcbxxDao.selectList(qw3);

        try {
            // 4.将营销中间库催收信息写入本地库（默认全部有效）
            for (YxxtYxzjkZwCsxxEntity yxCsxx : yxcsxxList) {
                YxzjkZwCsxxEntity sesCsxx = new YxzjkZwCsxxEntity();
                CommonUtil.copySameBean(yxCsxx, sesCsxx);   //将yxCsxx的数据复制到sesCsxx
                if (sesCsxxDao.selectById(sesCsxx.getTsbs()) == null) {
                    sesCsxx.setIsValid("Y");
                    sesCsxxDao.insert(sesCsxx);
                }
            }

            // 5.将营销中间库银行账号信息写入本地库
            for (YxxtYxzjkKhYhzhEntity yxYhzh : yxyhzhList) {
                YxzjkKhYhzhEntity sesYhzh = new YxzjkKhYhzhEntity();
                CommonUtil.copySameBean(yxYhzh, sesYhzh);
                if (sesYhzhDao.selectById(sesYhzh.getTsbs()) == null) {
                    sesYhzhDao.insert(sesYhzh);
                }
            }

            // 6.将营销中间库抄表信息写入本地库
            for (YxxtYxzjkLcCbxxEntity yxCbxx : yxcbxxList) {
                YxzjkLcCbxxEntity sesCbxx = new YxzjkLcCbxxEntity();
                CommonUtil.copySameBean(yxCbxx, sesCbxx);
                if (sesCbxxDao.selectById(sesCbxx.getTsbs()) == null) {
                    sesCbxxDao.insert(sesCbxx);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("将营销中间库催收信息写入本地库出错！");
        }
    }

    /**
     * 调用存储过程进行号码去重处理
     * @param yxpch
     */
    public void p_handle_phone_numbers(String yxpch) {
        Map<String, Object> param = new HashMap<>();
        param.put("in_yxpch", yxpch);
        sesCsxxDao.p_handle_phone_numbers(param);
        if (!"1".equals(param.get("out_code"))) {
            throw new RuntimeException(String.valueOf(param.get("out_error")));
        }
    }

    /**
     * 获取有效的催收信息（号码去重后的有效催费用户信息）
     * @param dqbm
     * @param yxpch
     * @return
     */
    public List<YxzjkZwCsxxEntity> getIsValidCsxx(String dqbm, String yxpch) {
        QueryWrapper<YxzjkZwCsxxEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("DQBM", dqbm);
        queryWrapper.eq("YXPCH", yxpch);
        queryWrapper.eq("IS_VALID", "Y");
        return sesCsxxDao.selectList(queryWrapper);
    }

    /**
     * 根据营销批次号更新任务号
     * @param yxpch
     * @param task_id
     */
    public Integer updateTaskIdByYxpch(String yxpch, String task_id) {
        UpdateWrapper<YxzjkZwCsxxEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("YXPCH", yxpch).set("TASK_ID", task_id);
        return sesCsxxDao.update(null, updateWrapper);
    }
}